C++17
introduced inline variables. They provide a proper way to define global variables in header files. Before inline variables, it
wasn’t possible to simply define global variables without compile or link errors:
struct A {
static std::string s1 = "s1"; // doesn’t compile
static std::string s2;
};
A::s2 = "s2"; // doesn’t link, violates the one definition rule
std::string s3 = "s3"; // doesn’t link, violates the one definition rule
Instead, you had to resort to less readable inconvenient workarounds like variable templates or functions that return a static object. These
workarounds will initialize the variables when used instead of the start of the program, which might be inconvenient depending on the program.
This rule will detect these workarounds and suggest using inline variables instead.
Noncompliant code example
struct Clazz {
static std::string& getS1() { // Noncompliant
static std::string s1 = "s1";
return s1;
}
static Clazz const& getSelf() { // Noncompliant
static Clazz self;
return self;
}
};
inline std::string& getS2() { // Noncompliant
static std::string s2 = "s2";
return s2;
}
template <typename T = std::string>
T s3 = "s3"; // Noncompliant. Available starting C++14
Compliant solution
struct Clazz {
inline static std::string s1 = "s1"; // Compliant,
static Clazz self;
};
inline Class Clazz::self; // Compliant
// Out of line definition is required for `Clazz` to be complete.
inline std::string s2 = "s2"; // Compliant